package com.ktwlsoft.fundmanage.domain.business;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.ktwlsoft.fundmanage.domain.entity.BaseFundRecord;
import com.ktwlsoft.fundmanage.domain.entity.FundInRecord;
import com.ktwlsoft.fundmanage.domain.entity.FundOutRecord;
import com.ktwlsoft.fundmanage.domain.entity.FundSuperviseAccept;
import com.ktwlsoft.fundmanage.domain.entity.TransferApply;
import com.ktwlsoft.fundmanage.domain.entity.pictureconfig.SignCredential;
import com.ktwlsoft.fundmanage.domain.repository.FundInRecordRepository;
import com.ktwlsoft.fundmanage.domain.repository.FundOutRecordRepository;
import com.ktwlsoft.fundmanage.domain.repository.FundSuperviseAcceptRepository;
import com.ktwlsoft.fundmanage.domain.repository.HouseRelatedPersonRepository;
import com.ktwlsoft.fundmanage.domain.repository.TransferApplyRepository;
import com.ktwlsoft.fundmanage.mapper.CurrencyMapper;
import com.ktwlsoft.fundmanage.mapper.IFundRecordMapper;
import com.ktwlsoft.fundmanage.mapper.IFundSuperviseAcceptMapper;
import com.ktwlsoft.fundmanage.mapper.ITransferApplyMapper;
import com.ktwlsoft.fundmanage.payload.BaseResult;
import com.ktwlsoft.fundmanage.payload.IAccountUser;
import com.ktwlsoft.fundmanage.payload.ResultType;
import com.ktwlsoft.fundmanage.payload.exceptions.BusinessError;
import com.ktwlsoft.fundmanage.payload.exceptions.NotFundException;
import com.ktwlsoft.fundmanage.payload.fundIn.TransferCancelRequest;
import com.ktwlsoft.fundmanage.payload.fundOut.*;
import com.ktwlsoft.fundmanage.service.pictureconfig.SignCredentialInfoService;
import com.ktwlsoft.fundmanage.service.pictureconfig.SignCredentialService;
import com.ktwlsoft.fundmanage.utils.KeyWorkerUtil;
import com.ktwlsoft.fundmanage.utils.UserUtils;

import lombok.Getter;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.validation.constraints.NotNull;

/**
 * @author LanJian
 */
@Service
public class FundOutService {

    /**
     * 划款单
     */
    @Getter
    private final TransferApplyRepository transferApplyRepository;

    /**
     * 划款单
     */
    private final ITransferApplyMapper transferApplyMapper;

    /**
     * 资金受理业务
     */
    private final IFundSuperviseAcceptMapper fundSuperviseAcceptMapper;

    /**
     * 房屋关系人
     */
    private final HouseRelatedPersonRepository houseRelatedPersonRepository;

    private final CurrencyMapper currencyMapper;

    @Getter
    private final FundOutRecordRepository fundOutRecordRepository;

    @Getter
    private final FundSuperviseAcceptRepository fundSuperviseAcceptRepository;

    @Getter
    private final FundInRecordRepository fundInRecordRepository;

    private final SignCredentialService signCredentialService;

    private final SignCredentialInfoService signCredentialInfoService;

    private final IFundRecordMapper fundRecordMapper;

    public FundOutService(TransferApplyRepository transferApplyRepository, ITransferApplyMapper transferApplyMapper,
                          IFundSuperviseAcceptMapper fundSuperviseAcceptMapper, HouseRelatedPersonRepository houseRelatedPersonRepository,
                          CurrencyMapper currencyMapper, FundOutRecordRepository fundOutRecordRepository,
                          FundSuperviseAcceptRepository fundSuperviseAcceptRepository, FundInRecordRepository fundInRecordRepository,
                          SignCredentialService signCredentialService, SignCredentialInfoService signCredentialInfoService,
                          IFundRecordMapper fundRecordMapper) {
        this.transferApplyRepository = transferApplyRepository;
        this.transferApplyMapper = transferApplyMapper;
        this.fundSuperviseAcceptMapper = fundSuperviseAcceptMapper;
        this.houseRelatedPersonRepository = houseRelatedPersonRepository;
        this.currencyMapper = currencyMapper;
        this.fundOutRecordRepository = fundOutRecordRepository;
        this.fundSuperviseAcceptRepository = fundSuperviseAcceptRepository;
        this.fundInRecordRepository = fundInRecordRepository;
        this.signCredentialService = signCredentialService;
        this.signCredentialInfoService = signCredentialInfoService;
        this.fundRecordMapper = fundRecordMapper;
    }

    /**
     * 保存划款单数据, 作者：兰坚
     *
     * @param apply             划款单
     * @param processInstanceId 流程Id
     * @return 划款单
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<TransferApply> saveTransferApply(TransactRequest apply, String processInstanceId) {
        IAccountUser user = UserUtils.getUser();
        if (user.getName().length() == 0) {
            throw new BusinessError("未获取用户信息！");
        }
        TransferApply transferApply = new TransferApply();

        if (apply.getTransId() > 0) {
            TransferApply old = transferApplyRepository.findById(apply.getTransId()).orElse(null);
            if (old == null) {
                return BaseResult.body("生成划款单：旧划款单未找到！", ResultType.BUSINESS_ERROR);
            }
            old.setState(TransferApply.State.CANCEL_HANDED);
            transferApply.setReturned(true);
            transferApplyRepository.save(old);
        }
        transferApply.setId(KeyWorkerUtil.nextId());
        transferApply.setTsCode(apply.getTsCode());
        transferApply.setSeller(apply.getSeller());
        transferApply.setSellerId(apply.getSellerId());
        transferApply.setBuyer(apply.getBuyer());
        transferApply.setBuyerId(apply.getBuyerId());
        transferApply.setBankName(apply.getBankName());
        transferApply.setBankCardNum(apply.getBankAccount());
        transferApply.setReceiver(apply.getReceiperName());
        transferApply.setReceiverId(apply.getReceiperId());
        transferApply.setSellerCertificateNumber(apply.getSellerCertificateNumber());
        transferApply.setReceiverBankName(apply.getOpeningBank());
        transferApply.setReceiverBankCardNum(apply.getOpeningAcount());
        transferApply.setAmount(apply.getAmount());
        transferApply.setAmountCh(apply.getAmountCh());
        transferApply.setUseType(apply.getUseType());
        transferApply.setSubBank(apply.getSubBank());
        transferApply.setSourceType(apply.getSourceType());
//        transferApply.setApprovalFlow(apply.getApprovalFlow());
        if (apply.getApprovalFlow() == null) {
            transferApply.setApprovalFlow(KeyWorkerUtil.nextId());
        } else {
            transferApply.setApprovalFlow(apply.getApprovalFlow());
        }

        transferApply.setFundInCode(apply.getFCode());
        transferApply.setState(TransferApply.State.NORMAL);
        transferApply.setAuditState(TransferApply.AuditStatus.WAIT);
        transferApply.setPayer(apply.getPayer());
        if (apply.getPayerId() != null) {
            transferApply.setPayerId(apply.getPayerId());
        }
        transferApply.setOperator(user.getName());
        transferApply.setOperatorId(user.getUserId());
        transferApply.setTransferType(apply.getTransactType());
        transferApply.setFlowInstanceId(processInstanceId);
        transferApply.setThirdTransferType(apply.getThirdTransferType());
        transferApply.setSubOpeningBanck(apply.getSubOpeningBanck());
        transferApply.setReceiverCertificateType(apply.getSellerCertificateType());
        transferApply.setReceiverCertificateNumber(apply.getSellerCertificateNumber());
        transferApplyRepository.save(transferApply);
        this.updateFiles(String.valueOf(transferApply.getId()), apply.getSignCredentials());
        return BaseResult.ok(transferApply);
    }

    private void updateFiles(String businessId, List<SignCredential> signCredentials) {
        signCredentialService.deleteByBusiId(businessId);
        signCredentialInfoService.deleteByBusiId(businessId);
        signCredentialInfoService.save(signCredentials, businessId);
    }

    /**
     * 划款单审核 作者：兰坚
     *
     * @param approval 审核
     * @param transId  主键
     * @return 审核后的实体
     */
    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> transferApproval(boolean approval, long transId) {
        TransferApply transferApply = transferApplyRepository.findById(transId).orElse(null);
        if (transferApply != null) {
            long flowCode = KeyWorkerUtil.nextId();
            transferApply.setApprovalFlow(flowCode);
            transferApply.setAuditState(approval ? TransferApply.AuditStatus.PASSED : TransferApply.AuditStatus.UNPASSED);
            transferApplyRepository.save(transferApply);
            return BaseResult.ok(transferApply);
        } else {
            throw new NotFundException("Can't find this transfer apply!");
        }
    }

    // @Transactional(rollbackFor = Exception.class)
    // public List<TransferApply> transferApprovalBatch(TransferApprovalBatchRequest
    // request) {
    // List<TransferApply> transferApplies = new ArrayList<>();
    // long approvalFlow = KeyWorkerUtil.nextId();
    // for (TransferApprovalBatchRequest.TransferApproval approval :
    // request.getTransferApprovals()) {
    // TransferApply transferApply =
    // transferApplyRepository.findById(approval.getTransId()).orElse(null);
    // if (transferApply != null) {
    // transferApply.setApprovalFlow(approvalFlow);
    // transferApply.setAuditState(request.isApproval() ?
    // TransferApply.AuditStatus.PASSED : TransferApply.AuditStatus.UNPASSED);
    // transferApplyRepository.save(transferApply);
    // transferApplies.add(transferApply);
    // }
    // }
    // return transferApplies;
    // }

    /**
     * 查找划款单数据
     *
     * @param transferId 划款单id
     * @return 划款单
     */
    public TransferApply findTransferApply(long transferId) {
        return transferApplyRepository.findById(transferId).get();
    }

    /**
     * 保存资金出账记录 作者：兰坚
     *
     * @param fundOutRecord 资金出账
     * @return 保存的资金出账
     */
    public FundOutRecord saveFundOutRecord(FundOutRecord fundOutRecord) {
        return fundOutRecordRepository.save(fundOutRecord);
    }

    /**
     * 更新划款单 作者：兰坚
     *
     * @param transferApply 划款单申请
     * @return 更新后划款单
     */
    public BaseResult<?> transferModify(TransferApply transferApply) {
        return BaseResult.ok(transferApplyRepository.save(transferApply));
    }

    /**
     * 设置退款划款单其他收款人信息
     *
     * @param apply 其他收款人信息
     * @return 修改是否成功
     */
    public TransferApply updateTransferApply(TransferApply apply) {
        IAccountUser user = UserUtils.getUser();
        apply.setOperator(user.getName());
        apply.setOperatorId(user.getUserId());
        return transferApplyRepository.save(apply);
    }

    /**
     * 划款单列表 on 2019/9/10 17:45
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param request  request
     * @return BaseResult<?>
     */
    public BaseResult<?> findTransferApplyPage(int pn, int pageSize, FindTransferApplyPageRequest request) {
        IAccountUser user = UserUtils.getUser();
        if (user.getUserId() == null || "".equals(user.getUserId().trim())) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("获取不到当前用户");
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("userId", user.getUserId());
        if (request.getKeyWords() != null && !"".equals(request.getKeyWords())) {
            jsonObject.put("keyWords", request.getKeyWords());
        }
        if (request.getAcceptanceDateStart() != null && !"".equals(request.getAcceptanceDateStart())) {
            jsonObject.put("acceptanceDateStart", request.getAcceptanceDateStart());
        }
        if (request.getAcceptanceDateEnd() != null && !"".equals(request.getAcceptanceDateEnd())) {
            jsonObject.put("acceptanceDateEnd", request.getAcceptanceDateEnd());
        }
        if (request.getOpeningDateStart() != null && !"".equals(request.getOpeningDateStart())) {
            jsonObject.put("openingDateStart", request.getOpeningDateStart());
        }
        if (request.getOpeningDateEnd() != null && !"".equals(request.getOpeningDateEnd())) {
            jsonObject.put("openingDateEnd", request.getOpeningDateEnd());
        }
        if (request.getApprovalDateStart() != null && !"".equals(request.getApprovalDateStart())) {
            jsonObject.put("approvalDateStart", request.getApprovalDateStart());
        }
        if (request.getApprovalDateEnd() != null && !"".equals(request.getApprovalDateEnd())) {
            jsonObject.put("approvalDateEnd", request.getApprovalDateEnd());
        }
        if (request.getTransferApplyDateStart() != null && !"".equals(request.getTransferApplyDateStart())) {
            jsonObject.put("transferApplyDateStart", request.getTransferApplyDateStart());
        }
        if (request.getTransferApplyDateEnd() != null && !"".equals(request.getTransferApplyDateEnd())) {
            jsonObject.put("transferApplyDateEnd", request.getTransferApplyDateEnd());
        }
        if (request.getDistrictCode() != null && !"".equals(request.getDistrictCode())) {
            jsonObject.put("districtCode", request.getDistrictCode());
        }
        if (request.getSuperviseBank() != null && !"".equals(request.getSuperviseBank())) {
            jsonObject.put("superviseBank", request.getSuperviseBank());
        }
        if (request.getTransferType() != null) {
            jsonObject.put("transferType", request.getTransferType().toString());
        }
        if (request.getAuditState() != null) {
            jsonObject.put("auditState", request.getAuditState().toString());
        }
        if (request.getDrawMoneyAdministrationType() != null
                && !"".equals(request.getDrawMoneyAdministrationType().trim())) {
            jsonObject.put("drawMoneyAdministrationType", request.getDrawMoneyAdministrationType());
        }
        if (request.getRecordState() != null) {
            jsonObject.put("recordState", request.getRecordState());
        }
        if (request.getTransferState() != null) {
            jsonObject.put("transferState", request.getTransferState());
        }
        if (request.getState() != null) {
            jsonObject.put("state", request.getState());
        }
        PageHelper.startPage(pn, pageSize);
        List<FundSuperviseAccept> list = fundSuperviseAcceptMapper.findTransferApplyPage(jsonObject);
        PageInfo<FundSuperviseAccept> pageInfo = new PageInfo<>(list);
        if (pageInfo.getList() != null && pageInfo.getList().size() > 0) {
            pageInfo.getList().forEach(value -> {
                JSONObject object = new JSONObject();
                object.put("tsCode", value.getTsCode());
                object.put("useType", TransferApply.UseType.FUNDOUT);
                value.setTransferApplies(transferApplyMapper.findList(object));
                value.setHouseRelatedPersonList(houseRelatedPersonRepository.findByTsCode(value.getTsCode()));
            });
        }
        return BaseResult.body(pageInfo, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 划款单管理-审核列表 on 2019/9/10 17:45
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param request  request
     * @return BaseResult<?>
     */
    public BaseResult<?> findTransferApplyToExaminePage(int pn, int pageSize, FindTransferApplyPageRequest request) {
        JSONObject jsonObject = new JSONObject();
        if (request.getKeyWords() != null && !"".equals(request.getKeyWords())) {
            jsonObject.put("keyWords", request.getKeyWords());
        }
        if (request.getOpeningDateStart() != null && !"".equals(request.getOpeningDateStart())) {
            jsonObject.put("openingDateStart", request.getOpeningDateStart());
        }
        if (request.getOpeningDateEnd() != null && !"".equals(request.getOpeningDateEnd())) {
            jsonObject.put("openingDateEnd", request.getOpeningDateEnd());
        }
        if (request.getApprovalDateStart() != null && !"".equals(request.getApprovalDateStart())) {
            jsonObject.put("approvalDateStart", request.getApprovalDateStart());
        }
        if (request.getApprovalDateEnd() != null && !"".equals(request.getApprovalDateEnd())) {
            jsonObject.put("approvalDateEnd", request.getApprovalDateEnd());
        }
        if (request.getTransferApplyDateStart() != null && !"".equals(request.getTransferApplyDateStart())) {
            jsonObject.put("transferApplyDateStart", request.getTransferApplyDateStart());
        }
        if (request.getTransferApplyDateEnd() != null && !"".equals(request.getTransferApplyDateEnd())) {
            jsonObject.put("transferApplyDateEnd", request.getTransferApplyDateEnd());
        }
        if (request.getDistrictCode() != null && !"".equals(request.getDistrictCode())) {
            jsonObject.put("districtCode", request.getDistrictCode());
        }
        if (request.getSuperviseBank() != null && !"".equals(request.getSuperviseBank())) {
            jsonObject.put("superviseBank", request.getSuperviseBank());
        }
        if (request.getTransferType() != null) {
            jsonObject.put("transferType", request.getTransferType().toString());
        }
        if (request.getAuditState() != null) {
            jsonObject.put("auditState", request.getAuditState().toString());
        }
        if (request.getDrawMoneyAdministrationType() != null
                && !"".equals(request.getDrawMoneyAdministrationType().trim())) {
            jsonObject.put("drawMoneyAdministrationType", request.getDrawMoneyAdministrationType());
        }
        if (request.getRecordState() != null) {
            jsonObject.put("recordState", request.getRecordState());
        }
        if (request.getTransferState() != null) {
            jsonObject.put("transferState", request.getTransferState());
        }
        List<findTransferApplyToExamineReturn> list = Lists.newArrayList();
        PageHelper.startPage(pn, pageSize);
        List<TransferApply> applies = transferApplyMapper.findTransferApplyPage(jsonObject);
        PageInfo pageInfo = new PageInfo<>(applies);
        if (applies.size() > 0) {
            for (TransferApply apply : applies) {
                boolean b = true;
                for (findTransferApplyToExamineReturn aReturn : list) {
                    if (aReturn.getApprovalFlow().equals(apply.getApprovalFlow())
                            && aReturn.getTsCode().equals(apply.getTsCode())) {
                        aReturn.getItem().add(apply);
                        b = false;
                        break;
                    }
                }
                if (b) {
                    findTransferApplyToExamineReturn aReturn = new findTransferApplyToExamineReturn();
                    aReturn.setTsCode(apply.getTsCode());
                    aReturn.setApprovalFlow(apply.getApprovalFlow());
                    aReturn.setOperator(apply.getOperator());
                    aReturn.setOperatorId(apply.getOperatorId());
                    List<TransferApply> applyList = Lists.newArrayList();
                    applyList.add(apply);
                    aReturn.setItem(applyList);
                    list.add(aReturn);
                }
            }
        }
        pageInfo.setList(list);
        pageInfo.setTotal(list.size());
        return BaseResult.body(pageInfo, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 划款单详情 on 2019/9/16 11:22
     *
     * @param id id
     * @return BaseResult<?>
     */
    public BaseResult<?> getFindTransferApplyDetails(Long id) {
        TransferApply transferApply = transferApplyRepository.findById(id).orElse(null);
        if (transferApply == null) {
            return BaseResult.body(id, ResultType.BUSINESS_ERROR).withMessage("该数据不存在");
        }
        return BaseResult.ok(transferApply);
    }

    /**
     * 资金划款-分页 on 2019/9/12 11:24
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param request  request
     * @return BaseResult<?>
     */
    public BaseResult<?> capitalDrawMoney(int pn, int pageSize, FindTransferApplyPageRequest request) {
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(request));
        if (request.getKeyWords() != null && !"".equals(request.getKeyWords())) {
            jsonObject.put("keyWords", request.getKeyWords());
        }
        if (request.getOpeningDateStart() != null && !"".equals(request.getOpeningDateStart())) {
            jsonObject.put("openingDateStart", request.getOpeningDateStart());
        }
        if (request.getOpeningDateEnd() != null && !"".equals(request.getOpeningDateEnd())) {
            jsonObject.put("openingDateEnd", request.getOpeningDateEnd());
        }
        if (request.getApprovalDateStart() != null && !"".equals(request.getApprovalDateStart())) {
            jsonObject.put("approvalDateStart", request.getApprovalDateStart());
        }
        if (request.getApprovalDateEnd() != null && !"".equals(request.getApprovalDateEnd())) {
            jsonObject.put("approvalDateEnd", request.getApprovalDateEnd());
        }
        if (request.getTransferApplyDateStart() != null && !"".equals(request.getTransferApplyDateStart())) {
            jsonObject.put("transferApplyDateStart", request.getTransferApplyDateStart());
        }
        if (request.getTransferApplyDateEnd() != null && !"".equals(request.getTransferApplyDateEnd())) {
            jsonObject.put("transferApplyDateEnd", request.getTransferApplyDateEnd());
        }
        if (request.getDistrictCode() != null && !"".equals(request.getDistrictCode())) {
            jsonObject.put("districtCode", request.getDistrictCode());
        }
        if (request.getSuperviseBank() != null && !"".equals(request.getSuperviseBank())) {
            jsonObject.put("superviseBank", request.getSuperviseBank());
        }
        if (request.getTransferType() != null) {
            jsonObject.put("transferType", request.getTransferType().toString());
        }
        if (request.getAuditState() != null) {
            jsonObject.put("auditState", request.getAuditState().toString());
        }
        if (request.getTransfered() != null) {
            jsonObject.put("transfered", request.getTransfered());
        }
        PageHelper.startPage(pn, pageSize);
        List<TransferApply> applies = transferApplyMapper.capitalDrawMoney(jsonObject);
        return BaseResult.body(new PageInfo<>(applies), ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 退款管理-分页 on 2019/9/12 11:44
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param keyWrods keyWrods
     * @return BaseResult<?>
     */
    public BaseResult<?> refundAdministration(int pn, int pageSize, String keyWrods) {
        IAccountUser user = UserUtils.getUser();
        if (user.getUserId() == null || "".equals(user.getUserId().trim())) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("获取不到当前用户");
        }
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("userId", user.getUserId());
        if (keyWrods != null && !"".equals(keyWrods)) {
            jsonObject.put("keyWords", keyWrods);
        }
        PageHelper.startPage(pn, pageSize);
        List<FundSuperviseAccept> list = fundSuperviseAcceptMapper.refundAdministration(jsonObject);
        PageInfo<FundSuperviseAccept> pageInfo = new PageInfo<>(list);
        if (pageInfo.getList() != null && pageInfo.getList().size() > 0) {
            pageInfo.getList().forEach(value -> {
                JSONObject object = new JSONObject();
                object.put("tsCode", value.getTsCode());
                object.put("useType", TransferApply.UseType.REFUND.toString());
                object.put("transferType", TransferApply.TransferType.REFUND.toString());
                value.setTransferApplies(transferApplyMapper.findList(object));
                value.setHouseRelatedPersonList(houseRelatedPersonRepository.findByTsCode(value.getTsCode()));
                JSONObject object1 = new JSONObject();
                object1.put("tsCode", value.getTsCode());
                value.setFundInRecords(fundRecordMapper.findFundInRecord(object1));
            });
        }
        return BaseResult.body(pageInfo, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 退款划款单管理-分页 on 2019/9/12 12:24
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param request  request
     * @return BaseResult<?>
     */
    public BaseResult<?> refundMoneyOrderAdministrationPage(int pn, int pageSize,
                                                            RefundMoneyOrderAdministrationPageRequest request) {
        JSONObject jsonObject = new JSONObject();
        if (request.getOpeningDateStart() != null && !"".equals(request.getOpeningDateStart())) {
            jsonObject.put("openingDateStart", request.getOpeningDateStart());
        }
        if (request.getOpeningDateEnd() != null && !"".equals(request.getOpeningDateEnd())) {
            jsonObject.put("openingDateEnd", request.getOpeningDateEnd());
        }
        if (request.getApprovalDateStart() != null && !"".equals(request.getApprovalDateStart())) {
            jsonObject.put("approvalDateStart", request.getApprovalDateStart());
        }
        if (request.getApprovalDateEnd() != null && !"".equals(request.getApprovalDateEnd())) {
            jsonObject.put("approvalDateEnd", request.getApprovalDateEnd());
        }
        if (request.getTransferApplyDateStart() != null && !"".equals(request.getTransferApplyDateStart())) {
            jsonObject.put("transferApplyDateStart", request.getTransferApplyDateStart());
        }
        if (request.getTransferApplyDateEnd() != null && !"".equals(request.getTransferApplyDateEnd())) {
            jsonObject.put("transferApplyDateEnd", request.getTransferApplyDateEnd());
        }
        if (request.getLocation() != null && !"".equals(request.getLocation())) {
            jsonObject.put("location", request.getLocation());
        }
        if (request.getAuditState() != null) {
            jsonObject.put("auditState", request.getAuditState());
        }
        if (request.getBankName() != null && !"".equals(request.getBankName().trim())) {
            jsonObject.put("bankName", request.getBankName());
        }
        if (request.getTransferType() != null) {
            jsonObject.put("transferType", request.getTransferType());
        }
        if (request.getState() != null) {
            jsonObject.put("state", request.getState());
        }
        if (request.getKeyWords() != null && !"".equals(request.getKeyWords())) {
            jsonObject.put("keyWords", request.getKeyWords());
        }
        if (request.getUserId() != null && !"".equals(request.getUserId().trim())) {
            jsonObject.put("userId", request.getUserId());
        }
        if(request.getTransfered() != null && request.getTransfered() != 0){
            jsonObject.put("transfered", request.getTransfered() == 2?true:false);
        }
        List<findTransferApplyToExamineReturn> list = Lists.newArrayList();
        PageHelper.startPage(pn, pageSize);
        List<TransferApply> applies = transferApplyMapper.refundMoneyOrderAdministrationPage(jsonObject);
        PageInfo pageInfo = new PageInfo<>(applies);
        if (applies.size() > 0) {
            for (TransferApply apply : applies) {
                boolean b = true;
                for (findTransferApplyToExamineReturn aReturn : list) {
                    if (aReturn.getApprovalFlow().equals(apply.getApprovalFlow())
                            && aReturn.getTsCode().equals(apply.getTsCode())) {
                        aReturn.getItem().add(apply);
                        b = false;
                        break;
                    }
                }
                if (b) {
                    findTransferApplyToExamineReturn aReturn = new findTransferApplyToExamineReturn();
                    aReturn.setTsCode(apply.getTsCode());
                    aReturn.setOperator(apply.getOperator());
                    aReturn.setApprovalFlow(apply.getApprovalFlow());
                    aReturn.setOperatorId(apply.getOperatorId());
                    List<TransferApply> applyList = Lists.newArrayList();
                    applyList.add(apply);
                    aReturn.setItem(applyList);
                    list.add(aReturn);
                }
            }
        }
        pageInfo.setList(list);
        pageInfo.setTotal(list.size());
        return BaseResult.body(pageInfo, ResultType.BUSINESS_SUCCESS);
    }

    /**
     * 退回处理分页 on 2019/9/24 19:45
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param tsCode   tsCode
     * @return BaseResult<?>
     */
    public BaseResult<?> returnHandlePage(int pn, int pageSize, Long tsCode, Boolean forceCancel,
                                          TransferApply.State state) {
        JSONObject jsonObject = new JSONObject();
        if (tsCode == null || tsCode <= 0) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("交易编号为空");
        }
        jsonObject.put("tsCode", tsCode);
        if (forceCancel != null) {
            jsonObject.put("forceCancel", forceCancel);
        }
        if (state != null) {
            jsonObject.put("state", state.toString());
        }
        PageHelper.startPage(pn, pageSize);
        return BaseResult.ok(new PageInfo<>(transferApplyMapper.returnHandlePage(jsonObject)));
    }

    /**
     * 资金缴款-退回处理分页 on 2019/9/24 19:45
     *
     * @param pn       pn
     * @param pageSize pageSize
     * @param tsCode   tsCode
     * @return BaseResult<?>
     */
    public BaseResult<?> fundInReturnHandlePage(int pn, int pageSize, Long tsCode, FundInRecord.State state,
                                                Boolean isReturn) {
        JSONObject jsonObject = new JSONObject();
        if (tsCode == null || tsCode <= 0) {
            return BaseResult.body(null, ResultType.BUSINESS_ERROR).withMessage("交易编号为空");
        }
        jsonObject.put("tsCode", tsCode);
        if (isReturn != null) {
            jsonObject.put("isReturn", isReturn);
        }
        if (state != null) {
            jsonObject.put("state", state.toString());
        }
        PageHelper.startPage(pn, pageSize);
        PageInfo<JSONObject> info = new PageInfo<>(currencyMapper.fundInReturnHandlePage(jsonObject));
        if (info.getList() != null && info.getList().size() > 0) {
            info.getList().forEach(value -> {
                value.put("fCode", value.get("fCode") != null ? value.get("fCode") : "");
                value.put("createdAt", value.get("createdAt") != null ? value.get("createdAt") : "");
                value.put("netSignCode", value.get("netSignCode") != null ? value.get("netSignCode") : "");
                value.put("updatedAt", value.get("updatedAt") != null ? value.get("updatedAt") : "");
                value.put("tsCode", value.get("tsCode") != null ? value.get("tsCode") : "");
                value.put("dnCode", value.get("dnCode") != null ? value.get("dnCode") : "");
                value.put("approvalFlow", value.get("approvalFlow") != null ? value.get("approvalFlow") : "");
                value.put("flowInstanceId", value.get("flowInstanceId") != null ? value.get("flowInstanceId") : "");
                value.put("isReturn", value.get("isReturn") != null ? value.get("isReturn") : "");
                value.put("isRevoke", value.get("isRevoke") != null ? value.get("isRevoke") : "");
                value.put("payMethod", value.get("payMethod") != null ? value.get("payMethod") : "");
                value.put("printCount", value.get("printCount") != null ? value.get("printCount") : "");
                value.put("receiptCode", value.get("receiptCode") != null ? value.get("receiptCode") : "");
                value.put("type", value.get("type") != null ? value.get("type") : "");
                value.put("cancelId", value.get("cancelId") != null ? value.get("cancelId") : "");
                value.put("cancelName", value.get("cancelName") != null ? value.get("cancelName") : "");
                value.put("payCheck", value.get("payCheck") != null ? value.get("payCheck") : "");
                value.put("payCheckTime", value.get("payCheckTime") != null ? value.get("payCheckTime") : "");
                value.put("payChecker", value.get("payChecker") != null ? value.get("payChecker") : "");
                value.put("payCheckerId", value.get("payCheckerId") != null ? value.get("payCheckerId") : "");
                value.put("payFlag", value.get("payFlag") != null ? value.get("payFlag") : "");
                value.put("payFlowCode", value.get("payFlowCode") != null ? value.get("payFlowCode") : "");
                value.put("payer", value.get("payer") != null ? value.get("payer") : "");
                value.put("receiverAccount", value.get("receiverAccount") != null ? value.get("receiverAccount") : "");
                value.put("receiverBank", value.get("receiverBank") != null ? value.get("receiverBank") : "");
                value.put("transferd", value.get("transferd") != null ? value.get("transferd") : "");
                value.put("hasTransfer", value.get("hasTransfer") != null ? value.get("hasTransfer") : "");
                value.put("state", value.get("state") != null ? value.get("state") : "");
                value.put("userId", value.get("userId") != null ? value.get("userId") : "");
                value.put("userName", value.get("userName") != null ? value.get("userName") : "");
                value.put("remark", value.get("remark") != null ? value.get("remark") : "");
                value.put("cancelOperator", value.get("cancelOperator") != null ? value.get("cancelOperator") : "");
                value.put("cancelOperatorId", value.get("cancelOperatorId") != null ? value.get("cancelOperatorId") : "");
                value.put("cancelTime", value.get("cancelTime") != null ? value.get("cancelTime") : "");
                value.put("amount", value.get("amount") != null ? value.get("amount") : "");
                value.put("payTime", value.get("payTime") != null ? value.get("payTime") : "");
                value.put("expenditureBank", value.get("expenditureBank") != null ? value.get("expenditureBank") : "");
                value.put("expenditureAccount", value.get("expenditureAccount") != null ? value.get("expenditureAccount") : "");
                value.put("payBank", value.get("payBank") != null ? value.get("payBank") : "");
                value.put("payAccount", value.get("payAccount") != null ? value.get("payAccount") : "");
                value.put("payerId", value.get("payerId") != null ? value.get("payerId") : "");
                value.put("inRemark", value.get("inRemark") != null ? value.get("inRemark") : "");
                value.put("cancelReson", value.get("cancelReson") != null ? value.get("cancelReson") : "");
                value.put("payChecker", value.get("payChecker") != null ? value.get("payChecker") : "");
            });
        }
        return BaseResult.ok(info);
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean fundOutCheck(long fCode, FundOutCheckRequest.OutApproval outApproval, Date expenditureTime, Long tsCode) {
        if (!fundOutRecordRepository.existsByFCode(fCode)) {
            throw new BusinessError("出账对账：未找到对应的出账数据");
        }
        IAccountUser user = UserUtils.getUser();
        if (user == null) {
            throw new BusinessError("登录用户未空！");
        }
        if (outApproval != FundOutCheckRequest.OutApproval.PASS) {
            if (fundOutRecordRepository.updateFundOutExp(fCode, new Date(), user.getName(), user.getUserId(), true, BaseFundRecord.State.CANCEL, false, expenditureTime) <= 0) {
                throw new BusinessError("出账对账：未能成功对账");
            }
        } else {
            if (fundOutRecordRepository.updateFundOutExp(fCode, new Date(), user.getName(), user.getUserId(), false, BaseFundRecord.State.NORMAL, true, expenditureTime) <= 0) {
                throw new BusinessError("出账对账：未能成功对账");
            }
        }

        FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(tsCode);
        // BigDecimal fundInAmount = fundInRecordRepository.queryDownPay(tsCode);

        if (fundSuperviseAccept.getAcceptState() != FundSuperviseAccept.AcceptState.CANCEL) {
            BigDecimal fundOutAmount = fundOutRecordRepository.queryLoan(tsCode);
            if (fundOutAmount == null) {
                fundOutAmount = BigDecimal.ZERO;
            }
            if (fundOutAmount.compareTo(fundSuperviseAccept.getSuperviseAmount()) == 0) {
                fundSuperviseAccept.setAcceptState(FundSuperviseAccept.AcceptState.FINISH);
            }
        }
        return true;
    }

    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> generateFundOut(long transId, String instanceId, String transferType, boolean isReturn,
                                         Date createdAt, String remark, String flowCode, BaseFundRecord.Type type) {
        TransferApply transferApply = transferApplyRepository.findById(transId).orElse(null);
        if (transferApply == null) {
            throw new BusinessError("未找到相应的划款单");
//            return BaseResult.body("未找到相应的划款单", ResultType.BUSINESS_ERROR);
        }
        IAccountUser user = UserUtils.getUser();
        transferApply.setTransfered(true);
        FundOutRecord fundOutRecord = new FundOutRecord();
        fundOutRecord.setReturn(isReturn);
        fundOutRecord.setFCode(KeyWorkerUtil.nextId());
        fundOutRecord.setFlowCode(KeyWorkerUtil.nextId());
        fundOutRecord.setTsCode(transferApply.getTsCode());
        fundOutRecord.setFlowInstanceId(instanceId);
        fundOutRecord.setNetSignCode(transferApply.getNetSignCode());
        fundOutRecord.setDnCode(transferApply.getId());
        fundOutRecord.setAmount(transferApply.getAmount());
        fundOutRecord.setTransferType(transferType);
        fundOutRecord.setUserName(user.getName());
        fundOutRecord.setUserId(user.getUserId());
        fundOutRecord.setExpenditureBank(transferApply.getReceiverBankName());
        fundOutRecord.setExpenditureAccount(transferApply.getReceiverBankCardNum());
        fundOutRecord.setSeller(transferApply.getReceiver());
        fundOutRecord.setFundInId(transferApply.getFundInCode());
        fundOutRecord.setState(FundOutRecord.State.NORMAL);
        fundOutRecord.setRemark(remark);
        fundOutRecord.setBankFlowCode(flowCode);
        fundOutRecord.setType(type);
        fundOutRecord.setTransferApplyTime(createdAt);
        saveFundOutRecord(fundOutRecord);
        transferApply.setFundOutCode(fundOutRecord.getFCode());
        transferApply.setTransferDate(new Date());

        if (isReturn == false) {
            // SET AMOUNT LEFT IN BUSINESS.
            FundSuperviseAccept fundSuperviseAccept = fundSuperviseAcceptRepository.findByTsCode(transferApply.getTsCode());
            if (fundSuperviseAccept.getAcceptState() == FundSuperviseAccept.AcceptState.CANCEL) {
                fundSuperviseAccept.setRefundState(FundSuperviseAccept.RefundState.GRANTED);
            }
            fundSuperviseAcceptRepository.save(fundSuperviseAccept);
        }
        fundOutRecordRepository.save(fundOutRecord);
        transferApplyRepository.save(transferApply);
        return BaseResult.ok(fundOutRecord);
    }

    public FundOutRecord findFundOut(long fCode) {
        return fundOutRecordRepository.findByFCode(fCode);
    }

    @Transactional(rollbackFor = Exception.class)
    public BaseResult<?> cancelOldAndGenerateNew(long oldFundOutFCode, long transId, String instanceId,
                                                 String transferType, Date createdAt, String remark, String flowCode, BaseFundRecord.Type fundType) {
        fundOutRecordRepository.updateState(BaseFundRecord.State.CANCEL_HANDLED, oldFundOutFCode);
        return this.generateFundOut(transId, instanceId, transferType, true, createdAt, remark, flowCode, fundType);
    }

    public BaseResult<?> findTransferApplyCancel() {
        try {
            String operatorId = UserUtils.getUser().getUserId();
            return BaseResult.ok(transferApplyRepository.findByOperatorIdAndState(operatorId, TransferApply.State.CANCEL));
        } catch (Exception e) {
            return BaseResult.ok(transferApplyRepository.findByOperatorIdAndState("unknown", TransferApply.State.CANCEL));
        }

    }

    @Transactional(rollbackFor = Exception.class)
    public boolean canTransferCancel(long approvalFlow, long transId) {
        List<TransferApply> transferApplies = transferApplyRepository.findByApprovalFlowAndState(approvalFlow, TransferApply.State.NORMAL);
        boolean canReturn = true;
        if (transferApplies.size() == 2) {
//            boolean isSame = transferApplies.get(0).getTransferType() == transferApplies.get(1).getTransferType();
//            canReturn = !(transferApplies.get(0).isTransfered() || transferApplies.get(1).isTransfered());
            boolean hasThird = transferApplies.get(0).getTransferType() == TransferApply.TransferType.THIRD ||
                    transferApplies.get(1).getTransferType() == TransferApply.TransferType.THIRD;
            if (hasThird) {
                long otherTransferId = transferApplies.get(0).getId() == transId ?
                        transferApplies.get(1).getId() :
                        transferApplies.get(0).getId();
                FundOutRecord fundOutRecord = fundOutRecordRepository.findByDnCode(otherTransferId);
                if (fundOutRecord != null) {
                    if (!fundOutRecord.isRevoke()) {
                        canReturn = false;
                    }
                }
            }
        }
        return canReturn;
    }

    public List<FundOutOrCancelRequest> generateTransferRequest(TransferCancelRequest request) {
        List<TransferApply> transferApplies = transferApplyRepository.findByApprovalFlowAndState(request.getApprovalFlow(), TransferApply.State.NORMAL);
        List<FundOutOrCancelRequest> fundOutOrCancelRequests = new ArrayList<>();
        boolean hasThird = false;

        for (TransferApply t : transferApplies) {
            if (t.getTransferType() == TransferApply.TransferType.THIRD) {
                hasThird = true;
            }
            FundOutOrCancelRequest fundOutOrCancelRequest = new FundOutOrCancelRequest(t.getId(), new Date(), t.getType(), request.getRemark(), null, null);
            fundOutOrCancelRequest.setInstanceId(t.getFlowInstanceId());
            fundOutOrCancelRequests.add(fundOutOrCancelRequest);
        }
        if (!hasThird) {
            TransferApply special = transferApplyRepository.findById(request.getTransId()).orElse(null);
            fundOutOrCancelRequests.clear();
            if (special != null) {
                FundOutOrCancelRequest fundOutOrCancelRequest = new FundOutOrCancelRequest(special.getId(), new Date(),
                        special.getType(), request.getRemark(), null, null);
                fundOutOrCancelRequest.setInstanceId(special.getFlowInstanceId());
                fundOutOrCancelRequests.add(fundOutOrCancelRequest);
            }
        }
        return fundOutOrCancelRequests;
    }

    @Transactional(rollbackFor = Exception.class)
    public boolean cancelFundOut(long fCode) {
        return fundOutRecordRepository.updateState(BaseFundRecord.State.CANCEL_HANDLED, fCode) > 0;
    }

    public boolean doTransferApplyExist(Long tsCode, long fCode) {
        return transferApplyRepository.existsByTsCodeAndFundInCodeAndState(tsCode, fCode, TransferApply.State.NORMAL);
    }

    public boolean hasTransApply(long tsCode) {
        List<TransferApply> applies = transferApplyRepository.findByTsCode(tsCode);
        return applies != null;
    }
}
